#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
PLY到PCD格式转换工具
用于将PLY文件转换为PCD格式，便于PCL库处理
"""

import open3d as o3d
import os
import sys
import glob
import argparse

def convert_ply_to_pcd(input_path, output_path=None, binary=False):
    """
    将PLY文件转换为PCD格式
    
    Args:
        input_path: 输入PLY文件路径
        output_path: 输出PCD文件路径（可选，默认替换扩展名）
        binary: 是否保存为二进制格式（默认ASCII格式）
    """
    try:
        # 检查输入文件是否存在
        if not os.path.exists(input_path):
            print(f"错误：文件不存在 {input_path}")
            return False
        
        # 读取PLY文件
        print(f"正在读取PLY文件: {input_path}")
        point_cloud = o3d.io.read_point_cloud(input_path)
        
        if len(point_cloud.points) == 0:
            print(f"警告：点云为空 {input_path}")
            return False
        
        # 生成输出路径
        if output_path is None:
            output_path = os.path.splitext(input_path)[0] + '.pcd'
        
        # 保存为PCD格式
        print(f"正在保存PCD文件: {output_path}")
        print(f"格式: {'二进制' if binary else 'ASCII'}")
        
        success = o3d.io.write_point_cloud(output_path, point_cloud, write_ascii=not binary)
        
        if success:
            print(f"✓ 转换成功！")
            print(f"  点数: {len(point_cloud.points)}")
            if point_cloud.has_colors():
                print(f"  颜色信息: 已保留")
            else:
                print(f"  颜色信息: 无")
            print(f"  输出文件: {output_path}")
            
            # 显示文件大小
            file_size = os.path.getsize(output_path)
            if file_size > 1024 * 1024:
                print(f"  文件大小: {file_size / (1024 * 1024):.2f} MB")
            elif file_size > 1024:
                print(f"  文件大小: {file_size / 1024:.2f} KB")
            else:
                print(f"  文件大小: {file_size} bytes")
            
            return True
        else:
            print(f"✗ 保存失败: {output_path}")
            return False
            
    except Exception as e:
        print(f"转换失败: {str(e)}")
        return False

def batch_convert(input_dir, output_dir=None, binary=False):
    """
    批量转换目录中的所有PLY文件
    
    Args:
        input_dir: 输入目录
        output_dir: 输出目录（可选，默认与输入目录相同）
        binary: 是否保存为二进制格式
    """
    if not os.path.exists(input_dir):
        print(f"错误：目录不存在 {input_dir}")
        return
    
    # 查找所有PLY文件
    ply_files = glob.glob(os.path.join(input_dir, "*.ply"))
    
    if not ply_files:
        print(f"在目录 {input_dir} 中未找到PLY文件")
        return
    
    print(f"找到 {len(ply_files)} 个PLY文件")
    print(f"输出格式: {'二进制PCD' if binary else 'ASCII PCD'}")
    print()
    
    success_count = 0
    for ply_file in ply_files:
        # 生成输出路径
        if output_dir:
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)
                print(f"创建输出目录: {output_dir}")
            basename = os.path.basename(ply_file)
            pcd_file = os.path.join(output_dir, os.path.splitext(basename)[0] + '.pcd')
        else:
            pcd_file = None
        
        # 转换文件
        if convert_ply_to_pcd(ply_file, pcd_file, binary):
            success_count += 1
        print()  # 空行分隔
    
    print(f"批量转换完成: {success_count}/{len(ply_files)} 个文件成功转换")

def main():
    parser = argparse.ArgumentParser(description='PLY到PCD格式转换工具')
    parser.add_argument('input', help='输入PLY文件或目录路径')
    parser.add_argument('-o', '--output', help='输出PCD文件或目录路径')
    parser.add_argument('-b', '--batch', action='store_true', help='批量转换模式（输入必须是目录）')
    parser.add_argument('--binary', action='store_true', help='保存为二进制PCD格式（默认ASCII格式）')
    
    args = parser.parse_args()
    
    if args.batch:
        # 批量转换模式
        batch_convert(args.input, args.output, args.binary)
    else:
        # 单文件转换模式
        if os.path.isdir(args.input):
            print("输入是目录，使用 -b 选项进行批量转换")
            return
        
        convert_ply_to_pcd(args.input, args.output, args.binary)

if __name__ == '__main__':
    # 如果没有命令行参数，显示帮助信息
    if len(sys.argv) == 1:
        print("PLY到PCD格式转换工具")
        print("=" * 50)
        print("使用方法:")
        print("  单文件转换: python3 convert_ply_to_pcd.py input.ply [-o output.pcd] [--binary]")
        print("  批量转换:   python3 convert_ply_to_pcd.py input_dir -b [-o output_dir] [--binary]")
        print()
        print("参数说明:")
        print("  --binary    保存为二进制PCD格式（文件更小，加载更快）")
        print("  默认        保存为ASCII PCD格式（文本格式，便于查看和调试）")
        print()
        print("示例:")
        print("  # ASCII格式转换")
        print("  python3 convert_ply_to_pcd.py /path/to/pointcloud.ply")
        print("  python3 convert_ply_to_pcd.py /path/to/ply_files -b")
        print()
        print("  # 二进制格式转换（推荐用于大文件）")
        print("  python3 convert_ply_to_pcd.py /path/to/pointcloud.ply --binary")
        print("  python3 convert_ply_to_pcd.py /path/to/ply_files -b --binary")
        print()
        print("  # 指定输出目录")
        print("  python3 convert_ply_to_pcd.py /path/to/ply_files -b -o /path/to/pcd_files")
        print()
        print("格式对比:")
        print("  ASCII PCD:  文本格式，便于查看和调试，文件较大")
        print("  二进制PCD:  二进制格式，文件小，加载快，PCL处理推荐")
    else:
        main()
